package org.pay;

import android.text.TextUtils;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.Strictness;
import com.google.gson.stream.JsonReader;

import org.pay.gate.model.PayGateReqModel;
import org.pay.gate.model.PayGateRespModel;
import org.pay.model.BaseModel;
import org.pay.model.PayRefundReqModel;
import org.pay.model.PayReqData;
import org.pay.utils.AES256Utils;
import org.pay.utils.Base64Utils;
import org.pay.utils.HashUtils;
import org.pay.utils.HexBinUtils;

import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class PayUtils {

    //「Kyle: 商店代號: 106832111290001
    //端末代號: 60000003
    //Key: 001d7aca9d3b132846b3895d93dbf627eb11ae186dcc2e90badf2b7e935f57d2
    //IV: ee91ee13bfd1f3b4abab0061091d500f
    //「Kyle: API base url
    //https://partner-api.epay365.com.tw/payments/v3

    private final String baseUrl = "https://partner-api.epay365.com.tw/payments/v3";
    //POST  API_MPPG1 Pay 交易扣款 執行端末設備一維及二維條碼之掃碼交易
    private final String reqPayUrl = "/pay";

    //POST API_MPPG2 Refund 交易退款 端末執行透過原交易訂單編號執行退款
    private final String reqRefundUrl = "/refund";

    //POST API_MPPG3 Check 交易查詢 執行端末查詢原交易之交易結果
    private final String reqCheckUrl = "/check";


    //
    private final String MerchantID = "106832111290001";
    //
    private final String TerminalID = "60000003";

    private final MediaType mediaType = MediaType.parse("application/json; charset=utf-8");

    private final String Key = "001d7aca9d3b132846b3895d93dbf627eb11ae186dcc2e90badf2b7e935f57d2";
    private final String IV = "ee91ee13bfd1f3b4abab0061091d500f";

    private final String charset = "UTF-8";


    public Map<String, String> buildReqHeader() {
        String contentType = "Content-Type";
        String contentTypeValue = "application/json";
        Map<String, String> header = new HashMap<>();
        header.put(contentType, contentTypeValue);
        //雷門商店代碼X-ePay-MerchantID
        header.put("X-ePay-MerchantID", MerchantID);
        // 雷門端末代碼
        header.put("X-ePay-TerminalID", TerminalID);
        header.put("X-ePay-DeviceType", "API");
        //廠商設備代碼
        header.put("X-Merchant-DeviceType", "QR68");
        //廠商設備序號
        header.put("X-Merchant-DeviceProfileId", "08001234");
        return header;
    }


    private String buildReqPayUrl() {
        return baseUrl + reqPayUrl;
    }

    private String buildReqCheckPayUrl() {
        return baseUrl + reqCheckUrl;
    }

    private String buildReqRefundPayUrl() {
        return baseUrl + reqRefundUrl;
    }


    /**
     * 支接口
     *
     * @param payReqData
     * @param callBack
     */
    public void doReqPayTask(PayReqData payReqData, PayCallback callBack) {
        Gson gson = new Gson();
        String payReqJson = gson.toJson(payReqData);
        reqPostJsonTask(buildReqPayUrl(), payReqJson, callBack);
    }

    /**
     * 查詢接口
     * <p>
     * 執行端末查詢原交易之交易結果
     *
     * @param param    "TxType"   "24" 查詢接口固定填字符串24
     *                 "BillNumber" 交易編號，需要查詢的交易編號
     * @param callback
     */
    public void doCheckPayTask(Map<String, String> param, PayCallback callback) {
        Gson gson = new Gson();
        String payReqJson = gson.toJson(param);
        reqPostJsonTask(buildReqCheckPayUrl(), payReqJson, callback);
    }



    /**
     * 交易退款接口
     * <p>
     * 端末執行透過原交易訂單編號執行退款
     *
     * @param model    只是比支付少一個詳情字段，其他都一致的
     * @param callback
     */
    public void doRefundPayTask(PayRefundReqModel model, PayCallback callback) {
        Gson gson = new Gson();
        String reqJson = gson.toJson(model);
        reqPostJsonTask(buildReqRefundPayUrl(), reqJson, callback);
    }


    private HttpLogInterceptor getHttpLoggingInterceptor() {
        //日誌顯示級別
        HttpLogInterceptor.Level level = HttpLogInterceptor.Level.BODY;
        //新建log攔截器
        HttpLogInterceptor loggingInterceptor = new HttpLogInterceptor(message ->
                Log.e("HTTP", " OkHttp Log :" + message));
        loggingInterceptor.setLevel(level);
        return loggingInterceptor;
    }

    //{"ErrorCode":"000","Message":"成功","ResponseCode":"OK","OrderNumber":"600000031735566077","BillNumber":"DH2024123021411535688239143495202622089765720547","PSP":38,"TxType":"22","LocalTime":"214120","LocalDate":"20241230","BuyerID":"130840413932698983","Amount":1000,"PSPName":"微信支付","TransactionID":"600000031735566077","ReceiptAmount":1000,"Carrier":"None","CouponAmount":0,"UsePoint":0,"RedeemDetail":null}
    private void reqPostJsonTask(String reqUrl, String jsonParm, PayCallback callBack) {
        byte[] contentBytes = null;
        try {
            contentBytes = jsonParm.getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }

        byte[] keyBytes = HexBinUtils.HexStr2Bytes(Key);
        byte[] initParam = HexBinUtils.HexStr2Bytes(IV);
        byte[] encrypt = AES256Utils.encode(keyBytes, initParam, contentBytes);
        String encryptBase = Base64Utils.encodeStr(encrypt);
        BaseModel baseModel = new BaseModel(encryptBase);


        String value = new Gson().toJson(baseModel);
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .addNetworkInterceptor(getHttpLoggingInterceptor())
                .build();
        Map<String, String> header = buildReqHeader();
        RequestBody requestBody = RequestBody.create(mediaType, value);
        Headers headers = Headers.of(header);
        Request request = new Request.Builder()
                .headers(headers)
                .url(reqUrl)
                .post(requestBody)
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                if (callBack != null) {
                    callBack.onFailure(call, e);
                }
            }


            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.e("TAG", "------------------->response.isSuccessful() : " + response.isSuccessful());
                String body = response.body().string();
                if (body != null && !body.isEmpty()) {
                    Log.e("TAG", "------------------->response body : " + body);
                }
                if (response.isSuccessful() || response.code() == 417) {
                    //支付失敗時候是417
                    Gson gson = new Gson();
                    BaseModel base = gson.fromJson(body, BaseModel.class);
                    Log.e("TAG", "------------------->response.BaseModel : " + base);
                    String newHash = HashUtils.digestSha256Value(base.getTransactionData());
                    boolean hashCheck = TextUtils.equals(base.getHashDigest(), newHash);
                    byte[] keyBytes = HexBinUtils.HexStr2Bytes(Key);
                    byte[] initParam = HexBinUtils.HexStr2Bytes(IV);
                    byte[] decrypt = AES256Utils.decode(keyBytes, initParam, Base64Utils.decode(base.getTransactionData()));
                    if (callBack != null) {
                        //   callBack.onSuccess(response, new String(decrypt));
                    }

                }


            }
        });
    }



    private String gateUrl = "http://34.81.233.7/api/pay";


    public void reqPayGateTask(PayGateReqModel payGateReqModel, PayCallback callBack) {
        payGateReqModel.setShopID(MerchantID);

        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .addNetworkInterceptor(getHttpLoggingInterceptor())
                .build();

        String value = new Gson().toJson(payGateReqModel);
        RequestBody requestBody = RequestBody.create(mediaType, value);

        Request request = new Request.Builder()
                .url(gateUrl)
                .post(requestBody)
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                if (callBack != null) {
                    callBack.onFailure(call, e);
                }
            }


            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String body = response.body().string();
                if (response.isSuccessful()) {
                    JsonReader jsonReader = new JsonReader(new StringReader(body));
                    // 設置 JsonReader 爲寬容模式
                    jsonReader.setStrictness(Strictness.LENIENT);
                    Gson gson = new Gson();
                    PayGateRespModel payRespData = gson.fromJson(jsonReader, PayGateRespModel.class);
                    //payRespData.paySuccess();
                    if (callBack != null) {
                        callBack.onSuccess(response, payRespData);
                    }
                } else {
                    callBack.onFailure(call, new IOException(response.message()));
                }

            }
        });
    }

    //   //BillNumber 交易編號 格式：shopID+YYYYMMDDHHmmss
    //    //BillNumber 例如店家編號為 1444 時 交易編號 144420221101164528
    public static String buildBillNumber(String shopId) {
        SimpleDateFormat dmDate = new SimpleDateFormat("yyyyMMddHHmmss");
        Date date = new Date();
        String dateran = dmDate.format(date);
        return shopId + dateran;
    }

    // 生成訂單號方法
    public static String randomOrderCode() {
        String fix = "DH"; // 前綴
        Integer len = 48; // 總長度，必須超過fix.length+dateran.length的長度
        // 獲取時間字符串
        SimpleDateFormat dmDate = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        Date date = new Date();
        String dateran = dmDate.format(date);
        // 生成隨機數
        Random ran = new Random();
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < len - fix.length() - dateran.length(); i++) {
            str.append(ran.nextInt(10));
        }
        // 拼接字符串
        return fix + dateran + str;
    }
}
